package se19team1e.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import se19team1e.dao.abstrakt.jaas.AccountDAO;
import se19team1e.dao.factory.DAOFactory;
import se19team1e.dao.factory.DAOFactorySelector;
import se19team1e.entity.AccountDTO;
import se19team1e.exception.DataAccessException;
import se19team1e.gui.LoginForm;
import se19team1e.util.StringUtil;

/**
 * 
 * The login controller class coordinates the operations between the screen,
 * form, and entity objects for login.
 * 
 * @author Li Guan Jun
 * 
 */
public class LoginController extends BaseController {

	/**
	 * Constructs the controller.
	 * 
	 * @param application
	 *            Reference to the current application instance.
	 */
	public LoginController(Application application) {
		super(application);
	}

	/**
	 * Initializes the controller.
	 * 
	 * <p>
	 * The login form is set as the current active screen.
	 * </p>
	 */
	public void initialize() {
		// get screen
		LoginForm screen = this.getApplication().getScreen(LoginForm.class);

		// initialize screen
		screen.initialize(this);

		// set as active screen
		this.getApplication().setCurrentScreen(screen);
	}

	/**
	 * Validates the login credentials and set the current logged in account if
	 * successfully.
	 * 
	 * <p>
	 * Displays an error message if it fails, using a message box.
	 * </p>
	 * 
	 * @param username
	 *            Login username credentials.
	 * @param password
	 *            Login password credentials.
	 * @throws DataAccessException
	 */
	public void login(String username, String password)
			throws DataAccessException {
		// validate first
		if (!this.validate(username, password)) {
			// failure, return
			return;
		}

		DAOFactory daoFactory = DAOFactorySelector.getDAOFactory();
		AccountDAO accountDAO = daoFactory.getAccountDAO();

		// get account if any
		AccountDTO account = accountDAO.retrieveByUsername(username);

		if (account == null) {
			// no such account, display error message
			this.displayInvalidUserErrorMessage();

			return;
		}

		// has account, validate!
		if (!account.login(password)) {
			// failure, display error message
			this.displayInvalidPasswordErrorMessage();

			return;
		}

		// success
		// sets current logged in account.
		this.getApplication().setCurrentAccount(account);

		// go to search form
		this.getApplication().selectSearchJobAdvert();
	}

	/**
	 * Validates the login credentials to see if it is valid for login.
	 * 
	 * <p>
	 * Returns false if validation fails.
	 * </p>
	 * <p>
	 * Displays an error message if it fails, using a message box.
	 * </p>
	 * 
	 * @param username
	 *            Login username credentials.
	 * @param password
	 *            Login password credentials.
	 * @return True if valid.
	 */
	private boolean validate(String username, String password) {
		// check for empty entry
		if (StringUtil.isEmptyOrNull(username)
				|| StringUtil.isEmptyOrNull(password)) {
			// failure, display error message
			this.displayMissingInputErrorMessage();

			return false;
		}

		return true;
	}

	/**
	 * Displays a message box indicating that input is missing.
	 */
	private void displayMissingInputErrorMessage() {
		this.displayMessage("Error", "Missing username or password",
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent event) {
						// do nothing
					}
				});
	}

	/**
	 * Displays a message box indicating that username is invalid.
	 */
	private void displayInvalidUserErrorMessage() {
		this.displayMessage("Error", "Invalid user", new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				// do nothing
			}
		});
	}

	/**
	 * Displays a message box indicating that password is invalid.
	 */
	private void displayInvalidPasswordErrorMessage() {
		this.displayMessage("Error", "Invalid password", new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				// do nothing
			}
		});
	}

}
